Link to this headingGraphQL

Automate Listing queries and mutations

Usual Endpoints:

  • /graphql
  • /v1/graphql
  • /v2/graphql
  • /graphql/console
  • /graphiql
  • /graphiql.php
  • /explorer
  • /altair
  • /playground

Possible Debug Flag:

  • &debug=1

Enumeration of Data
Enumerate GraphQL endpoints
Burp Plugin

Link to this headingQuery

  • Read only retrieve data
  • Can be used in GET or POST

Example Query Request:

POST /graphql HTTP/1.1 Accept: application/json Content-Type: application/json; charset=utf-8 Content-Length: 840 Host: example.com Connection: close Accept-Encoding: gzip, deflate User-Agent: okhttp/4.9.0 {"query": "mutation function($email:String!) { changePassword(email:$email) }", "variables": {"email": ""}}

Link to this headingMutation

  • Can be used in POST only

Make a change to the data. You can also make a query request to have it return new data.

Example Mutation Request:

POST /graphql HTTP/1.1 Accept: application/json Content-Type: application/json; charset=utf-8 Content-Length: 840 Host: example.com Connection: close Accept-Encoding: gzip, deflate User-Agent: okhttp/4.9.0 {"query": "query function($latitude:Float!, $longitude:Float!) { distanceToCoast(latitude:$latitude, longitude:$longitude) }", "variables": {"latitude": 1.1, "longitude": 1.1}}

Link to this headingIntrospection

This is enabled by default

POST Request:

POST /graphql HTTP/1.1 Accept: application/json Content-Type: application/json; charset=utf-8 Content-Length: 840 Host: example.com Connection: close Accept-Encoding: gzip, deflate User-Agent: okhttp/4.9.0 {"query":"query IntrospectionQuery { __schema { queryType { name } mutationType { name } subscriptionType { name } types { ...FullType } directives { name description locations args { ...InputValue } } } } fragment FullType on __Type { kind name description fields(includeDeprecated: true) { name description args { ...InputValue } type { ...TypeRef } isDeprecated deprecationReason } inputFields { ...InputValue } interfaces { ...TypeRef } enumValues(includeDeprecated: true) { name description isDeprecated deprecationReason } possibleTypes { ...TypeRef } } fragment InputValue on __InputValue { name description type { ...TypeRef } defaultValue } fragment TypeRef on __Type { kind name ofType { kind name ofType { kind name ofType { kind name ofType { kind name ofType { kind name ofType { kind name ofType { kind name } } } } } } } } "}

GET Request:

GET /graphql?query={__schema{queryType{name}mutationType{name}subscriptionType{name}types{...FullType}directives{name,description,locations,args{...InputValue}}}}fragment,FullType,on,__Type{kind,name,description,fields(includeDeprecated:true){name,description,args{...InputValue}type{...TypeRef}isDeprecated,deprecationReason}inputFields{...InputValue}interfaces{...TypeRef}enumValues(includeDeprecated:true){name,description,isDeprecated,deprecationReason}possibleTypes{...TypeRef}}fragment,InputValue,on,__InputValue{name,description,type{...TypeRef},defaultValue}fragment,TypeRef,on,__Type{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name}}}}}}}} HTTP/1.1 Accept: application/json Host: example.com Connection: close Accept-Encoding: gzip, deflate User-Agent: okhttp/4.9.0

Link to this headingViewing the Schema

Use Graphql Voyager to have a look at the Schema and their relationship.

Link to this headingAuthorization

No Built in Authorization. Look for IDs to change

Link to this headingBatching Attacks

GraphQL Batching Attack

Link to this headingSchema Recursion